package co.edu.unal.geditor.model;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.Serializable;

import co.edu.unal.geditor.controller.App;
import co.edu.unal.geditor.view.BoundBoxView;
import co.edu.unal.geditor.view.LineBoundBoxView;
import co.edu.unal.geditor.view.tools.Tool;

public class BoundBox implements Serializable {
	private static final long serialVersionUID = 1L;

	public BoundBox(Point ptUpLeft, Point ptBottomDown) {
		m_ptLeftUp = ptUpLeft;
		m_ptRightDown = ptBottomDown;

		createOtherPoints();
	
			m_view = new BoundBoxView(this);
		

	}

	public BoundBox(Rectangle r) {
		this(new Point(r.x, r.y), new Point(r.x + r.width, r.y + r.height));
	}

	public void normalize() {
		if (m_ptLeftUp.x > m_ptRightDown.x) {
			m_ptLeftUp.x ^= m_ptRightDown.x;
			m_ptRightDown.x ^= m_ptLeftUp.x;
			m_ptLeftUp.x ^= m_ptRightDown.x;
		}

		if (m_ptLeftUp.y > m_ptRightDown.y) {
			m_ptLeftUp.y ^= m_ptRightDown.y;
			m_ptRightDown.y ^= m_ptLeftUp.y;
			m_ptLeftUp.y ^= m_ptRightDown.y;
		}

	}

	public void createOtherPoints() {
		m_ptRightUp = new Point(m_ptRightDown.x, m_ptLeftUp.y);
		m_ptLeftDown = new Point(m_ptLeftUp.x, m_ptRightDown.y);
	}

	public void goSquare() {
		// make sure w & h > 0
		normalize();

		// w|h : arbitrary
		int width = m_ptRightDown.x - m_ptLeftUp.x;
		assert width > 0; // assert normalize()

		// h = w : square
		m_ptRightDown.y = m_ptLeftUp.y + width;
	}

	public boolean containedin(BoundBox bb) {
		boolean retorno = false;
		if (m_view.containedIn(bb)) {
			setSelected(true);
			retorno = true;
		} else {
			setSelected(false);
		}
		return retorno;
		/*
		 * return (m_ptLeftUp.x > bb.getLeftUp().x && m_ptLeftUp.y >
		 * bb.getLeftUp().y && m_ptRightDown.x < bb.getRightDown().x &&
		 * m_ptRightDown.y < bb.getRightDown().y);
		 */
	}

	public boolean contain(Point ptContained) {
		boolean retorno = false;
		if (m_view.containControlPoints(ptContained) && isSelected()) {
			retorno = true;
		} else {
			if (m_view.contain(ptContained)) {
				retorno = true;
			} else {
				App.getInstance().getCanvas().getActiveTool().setActiveAction(
						Tool.SELECT);
				App.getInstance().getCanvas().setCursor(
						new Cursor(Cursor.DEFAULT_CURSOR));
				App.getInstance().getCanvas().getActiveTool()
						.setActiveFeedbackGraphElement();
			}
		}
		return retorno;

		/*
		 * return (m_ptLeftUp.x < ptContained.x && m_ptLeftUp.y < ptContained.y
		 * && m_ptRightDown.x > ptContained.x && m_ptRightDown.y >
		 * ptContained.y);
		 */
	}

	public void paint(Graphics g) {
		if (isSelected()) {
			m_view.paint(g);
		} else {
			// Don't paint the BoundBox
		}
	}

	public Point getLeftUp() {
		return m_ptLeftUp;
	}

	public void setLeftUp(Point newLeftUp) {
		m_ptLeftUp = newLeftUp;
	}

	public Point getRightDown() {
		return m_ptRightDown;
	}

	public void setRightDown(Point newRightDown) {
		m_ptRightDown = newRightDown;
	}

	public int getWidth() {
		return Math.abs(m_ptRightDown.x - m_ptLeftUp.x);
	}

	public int getHeight() {
		return Math.abs(m_ptRightDown.y - m_ptLeftUp.y);
	}

	public Point getRightUp() {
		return m_ptRightUp;
	}

	public Point getLeftDown() {
		return m_ptLeftDown;
	}

	public boolean isSelected() {

		return m_bSelected;
	}

	public void setSelected(boolean selected) {
		m_bSelected = selected;

	}

	public BoundBoxView getView() {
		return m_view;
	}
	public void setView() {
		m_view = new BoundBoxView(this);
		m_view.chageCpPoints();
	}
	

	public void setAsLine(boolean isLine) {
		if (isLine){// Se usa un if por que el prorama ya esta diseñado con
			// if's para las líneas, es decir, en la línea 41 de
			// GraphElement se usa un if para saber si normalizar o
			// no
			m_view = new LineBoundBoxView(this);
		}
	}

	protected transient BoundBoxView m_view;

	private Point m_ptLeftUp;
	private Point m_ptRightDown;
	private Point m_ptRightUp;
	private Point m_ptLeftDown;
	protected boolean m_bSelected;

}
